package com.common.project.util;


import org.apache.commons.beanutils.ConvertUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.commons.lang3.StringUtils.isNotBlank;

public class ObjectUtils {

    //判断该对象是否: 返回ture表示所有属性为null  返回false表示不是所有属性都是nul
    public static boolean isAllFieldNull(Object obj) throws Exception{
        Class stuClass=(Class)obj.getClass();
        Field[] fs = stuClass.getDeclaredFields();
        boolean flag=true;
        for(Field f:fs){
            f.setAccessible(true);
            Object val=f.get(obj);//得到此属性的值
            if(val!=null){//只要有1个属性不为空,那么就不是所有的属性值都为空
                flag=false;
                break;
            }
        }
        return flag;
    }



    /**
     * map转对象方法
     *
     * @param entity
     * @param objectMap
     * @return
     */
    public static <T> T mapToObjModle(T entity, Map<String, Object> objectMap) {
        Map<String,Object> params=new HashMap<>();
        for(Map.Entry<String,Object> en:objectMap.entrySet()){
            String key = en.getKey();
            String keyneed = ReflectionUtils.lineToHump(key);
            Object value = en.getValue();
            params.put(keyneed,value);
        }

        Class<?> clazz = entity.getClass();
        // 得到对象的字段
        List<Field> fields = getAccessibleFields(clazz);
        // 迭代字段
        for (Field f : fields) {
            String name = f.getName();
            Object objVal = params.get(name);
            // 找到对应值，进行转化设置
            if (objVal != null) {
                try {
                    if (f.getType().equals(String.class)) {
                        objVal = String.valueOf(objVal);
                    } else if (!f.getType().isAssignableFrom(objVal.getClass())) {
                        if (isNotBlank(String.valueOf(objVal))) {
                            //转换依赖方法：org.apache.commons.beanutils.ConvertUtils.convert(Object, Class<?>)
                            objVal = ConvertUtils.convert(objVal, f.getType());
                        } else {
                            objVal = null;
                        }
                    }
                    Type genericType = f.getGenericType();
                    System.out.println(genericType.getTypeName());
                    if(genericType.getTypeName().equals("java.time.LocalDateTime")){
                        if(objVal!=null){
                            f.set(entity, localDateFromTimestamp((Timestamp)objVal));
                        }else{
                            f.set(entity, null);
                        }

                    }else{
                        f.set(entity, objVal);
                    }

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return entity;
    }


    public static LocalDateTime localDateFromTimestamp(Timestamp timestamp) {
        return LocalDateTime
                .ofInstant(timestamp.toInstant(), ZoneOffset.ofHours(0));
    }

    /**
     * 循环向上转型, 获取对象所有的DeclaredField
     *
     * 如向上转型到Object仍无法找到, 返回null.
     */
    public static List<Field> getAccessibleFields(final Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        for (Class<?> superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
            for (Field f : superClass.getDeclaredFields()) {
                boolean hasInSubClass = false;
                for (Field f2 : fields) {
                    if (f2.getName().equals(f.getName())) {
                        hasInSubClass = true;
                        break;
                    }
                }
                if (!hasInSubClass) {
                    makeAccessible(f);
                    fields.add(f);
                }
            }
        }
        return fields;
    }

    /**
     * 改变private/private的成员变量为public，尽量不调用实际改动的语句，避免JDK的SecurityManager抱怨。
     */
    public static void makeAccessible(Field field) {
        if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
                || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {
            field.setAccessible(true);
        }
    }


    public static Object mapToObject(Map<String, Object> map, Class<?> beanClass) throws Exception {
      if (map == null)
          return null;

       Object obj = beanClass.newInstance();

       org.apache.commons.beanutils.BeanUtils.populate(obj, map);

      return obj;
    }

     public static Map<?, ?> objectToMap(Object obj) {
        if(obj == null)
              return null;

        return new org.apache.commons.beanutils.BeanMap(obj);
    }



}
